import json

from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from goods.models import SKU
from orders.models import OrderInfo, OrderGoods

from utils.views import LoginRequiredJSONMixin
from ..users.models import Address


# Create your views here.


class OrderSettlementView(View):

    def get(self, request):

        user = request.user
        # 取所有没有逻辑删除的地址
        addresses = Address.objects.filter(is_deleted=False)
        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile
            })

        redis_cli = get_redis_connection('carts')
        pipeline = redis_cli.pipeline()
        # 获取选中状态
        pipeline.smembers('selected_%s' % user.id)
        # 获取购物车商品id和选中状态
        pipeline.hgetall('carts_%s' % user.id)
        # 执行管道
        result = pipeline.execute()
        sku_id_counts = result[1]
        selected_ids = result[0]

        selected_carts = {}
        for sku_id in selected_ids:
            selected_carts[int(sku_id)] = int(sku_id_counts[sku_id])

        sku_list = []
        for sku_id, count in selected_carts.items():
            sku = SKU.objects.get(pk=sku_id)
            #     3.6 需要将对象数据转换为字典数据
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'count': count,
                'default_image_url': sku.default_image.url,
                'price': sku.price
            })

            from decimal import Decimal
            freight = Decimal('10')

            context = {
                'skus': sku_list,
                'addresses': addresses_list,
                'freight': freight  # 运费
            }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'context': context})


from django.db import transaction


class OrderCommitView(LoginRequiredJSONMixin, View):
    def post(self, request):
        # 1.接收请求
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        user = request.user

        # user, address_id, pay_method
        # 2.验证数据
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '手环地址、支付方式--参数不全'})
        try:
            address = Address.objects.get(id=address_id)
        except Exception:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 400, 'errmsg': '支付方式不正确'})

        # 生成order_id。主键（自己生成）
        from django.utils import timezone
        from datetime import datetime
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S%f') + '%09d' % user.id

        # 支付状态由支付方式决定
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        # 总数量，总金额，运费
        total_count = 0
        from decimal import Decimal
        total_amount = Decimal('0')
        freight = Decimal('10.00')

        # 事物的开始点
        with transaction.atomic():

            point = transaction.savepoint()

            # 3.数据入库
            orderinfo = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )

            # 连接redis
            redis_cli = get_redis_connection('carts')
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id)
            selected_ids = redis_cli.smembers('selected_%s' % user.id)

            # 把redis数据转化成字典数据
            carts = {}
            for sku_id in selected_ids:
                carts[int(sku_id)] = int(sku_id_counts[sku_id])

            for sku_id, count in carts.items():
                while True:
                    sku = SKU.objects.get(id=sku_id)
                    if sku.stock<count:
                        # 事物回滚点
                        transaction.savepoint_rollback(point)

                        return JsonResponse({'code': 400, 'errmsg': '库存不足'})
                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()

                    # 使用乐观锁。先记录一个数据（任何一个都可以）
                    old_stock = sku.stock

                    new_stock = sku.stock - count
                    new_sales = sku.sales + count

                    result = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)

                    if result == 0:
                        continue


                    # 产品总数和价格总计
                    orderinfo.total_count += count
                    orderinfo.total_amount += (count * sku.price)

                    #       2.10 保存订单商品信息
                    OrderGoods.objects.create(
                        order=orderinfo,
                        sku=sku,
                        count=count,
                        price=sku.price
                    )
                    break

            orderinfo.save()

            # 事物提交点
            transaction.savepoint_commit(point)

        return JsonResponse({'code': 0, 'order_id': order_id})

            # hash
            # set
            # 根据商品id，查询商品信息
            # sku.price


        # 生成订单（订单基本信息表和订单商品信息表）
        # 3.1
        # 先保存订单基本信息
        #
        # 3.2
        # 再保存订单商品信息
        # 连接redis
        # 获取hash
        # 获取set
        # v
        # 最好重写组织一个数据，这个数据是选中的商品信息
        # 根据选中商品的id进行查询
        # 判断库存是否充足，
        # 如果充足，则库存减少，销量增加
        # 如果不充足，下单失败
        # 保存订单商品信息
        # 4.
        # 返回响应
        #
        # 一。接收请求
        # user, address_id, pay_method
        # 二。验证数据
        # order_id
        # 主键（自己生成）
        # 支付状态由支付方式决定
        # 总数量，总金额， = 0
        # 运费
        # 三。数据入库
        # 生成订单（订单基本信息表和订单商品信息表）
        # 1.
        # 先保存订单基本信息
        #
        # 2
        # 再保存订单商品信息
        # 2.1
        # 连接redis
        # 2.2
        # 获取hash
        # 2.3
        # 获取set
        # 2.4
        # 遍历选中商品的id，
        # 最好重写组织一个数据，这个数据是选中的商品信息
        # {sku_id: count, sku_id: count}
        #
        # 2.5
        # 遍历
        # 根据选中商品的id进行查询
        # 2.6
        # 判断库存是否充足，
        # 2.7
        # 如果不充足，下单失败
        # 2.8
        # 如果充足，则库存减少，销量增加
        # 2.9
        # 累加总数量和总金额
        # 2.10
        # 保存订单商品信息
        # 3.
        # 更新订单的总金额和总数量
        # 4.
        # 将redis中选中的商品信息移除出去
        # 四。返回响应